VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "cThreadWrapper"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit 'it's a good idea, to wrap your Remote-Threads in its own Wrapper-Class
 
Private Type ThreadInitDirectCOM
  Param As Long 'User-Param (given into the ThreadMain-Method of the COM-Dll)
  hThread As Long 'filled from Thread (instantly, after STARTCOMOBJECT() returns)
  ThreadID As Long 'filled from Thread (if fully initialized, some msec after STARTCOMOBJECT())
  Reserved(0 To 127) As Long
  
  'userdefined Params can be placed here...
  FPS As Long 'will reflect the current FPS of the Remote-Thread
  CancelThread As Boolean 'will be used to signalize Thread-Cancelling to the Remote-Thread
End Type

'this is the call which ensures a new STA with a regfree loaded AX-Dll-Class-Instance in it...
Private Declare Function STARTCOMOBJECT Lib "DirectCom" (FName As String, ClassName As String, TI As Any) As Long

'and below just some accompanying APIs we use here in the wrapper-class, to handle the Memory-Sharing and the Closing of the Remote-Thread
Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (Arr() As Any) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal mSec As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private TI() As ThreadInitDirectCOM 'will host the TI-allocation, which we create here in the Main-Thread
 
Private Sub Class_Initialize() 'prepare the TI-Array (which has only a single "Index-Slot" and is shared with the Remote-Thread)
  ReDim TI(0 To 0) 'we allocate the SharedMem-Array here in the Main-Thread
        TI(0).Param = ArrPtr(TI) 'the Param-Member is, what gets passed into the ThreadMain-Function of the Remote-Class
End Sub

Public Sub StartThread()
  STARTCOMOBJECT App.Path & "\Bin\ThreadLib.dll", "cThread", TI(0) 'start the Thread along with the ThreadLib.dll-cThread-Class regfree
End Sub

Public Property Get ThreadID() As Long
  ThreadID = TI(0).ThreadID '<- the .ThreadID-member of TI gets filled in the upstarting Remote-Thread
End Property

Public Property Get FPS() As Long
  FPS = TI(0).FPS '<- the .FPS-member of TI gets filled and updated in the Remote-Thread
End Property

Private Sub Class_Terminate() 'this ensures, that the Remote-Thread-Class dies along with this Wrapper-Class
  TI(0).CancelThread = True 'signalize the Remote-Thread, that we want to close it
  Sleep 50 'give the Remote-Thread some time, after we signaled it to close itself (in the line above)
  CloseHandle TI(0).hThread 'just to avoid Handle-Leakage
End Sub
